import { commands, ExtensionContext } from 'vscode';
import { RTContextConst, UserConst } from '../constants';
import { AwaitNotify } from '../utils';
import { VirtualFileSystem } from '../virtual-workspaces';
import { PluginConfig } from './plugin-config';

/**
 * 全局对象，用于存储一些全局配置 or 插件初始化后给的内容
 *
 * @author chitanda
 * @date 2022-12-12 16:12:40
 * @class Global
 */
class Global {
  /**
   * 插件完成前期准备工作，并且异步操作也已经完成
   *
   * @author chitanda
   * @date 2022-12-12 18:12:33
   */
  readonly complete_notify = new AwaitNotify();

  /**
   * 插件 vscode 配置
   *
   * @author chitanda
   * @date 2022-12-12 21:12:34
   */
  readonly config = new PluginConfig();

  /**
   * 当前插件匹配的虚拟文件系统
   *
   * @author chitanda
   * @date 2022-12-14 11:12:07
   */
  readonly vfs = new VirtualFileSystem();

  protected _complete = false;

  /**
   * 插件是否已经准备完毕
   *
   * @author chitanda
   * @date 2022-12-12 20:12:31
   * @protected
   */
  get complete(): boolean {
    return this._complete;
  }

  protected _ctx!: ExtensionContext;

  /**
   * vscode 插件上下文
   *
   * @author chitanda
   * @date 2022-12-12 17:12:08
   * @readonly
   * @type {ExtensionContext}
   */
  get ctx(): ExtensionContext {
    return this._ctx;
  }

  protected _token: string = '';

  /**
   * 用户认证标识
   *
   * @author chitanda
   * @date 2022-12-12 17:12:41
   * @readonly
   * @type {string}
   */
  get token(): string {
    return this._token;
  }

  /**
   * 插件初始化时调用
   *
   * @author chitanda
   * @date 2022-12-12 17:12:51
   * @param {ExtensionContext} context
   * @return {*}  {Promise<void>}
   */
  async init(context: ExtensionContext): Promise<void> {
    this._ctx = context;
    // 从插件中获取认证信息
    this._token = (await this.ctx.secrets.get(UserConst.TOKEN)) || '';
    // 根据认证信息设置是否已登录
    this.setContext(RTContextConst.HAS_ACCOUNT, !!this._token);
    this._complete = true;
    this.complete_notify.notifyAll();
  }

  /**
   * 设置用户标识
   *
   * @author chitanda
   * @date 2022-12-12 17:12:51
   * @param {string} token
   * @return {*}  {Thenable<void>}
   */
  setToken(token: string): Thenable<void> {
    this._token = token;
    if (token) {
      this.setContext(RTContextConst.HAS_ACCOUNT, true);
      return this.ctx.secrets.store(UserConst.TOKEN, token);
    }
    this.setContext(RTContextConst.HAS_ACCOUNT, false);
    return this.ctx.secrets.delete(UserConst.TOKEN);
  }

  /**
   * 设置 vscode 运行上下文，可以在 package.json 中用 wen 的地方使用
   *
   * @author chitanda
   * @date 2022-12-12 20:12:29
   * @param {string} key
   * @param {unknown} val
   */
  setContext(key: string, val: unknown): void {
    commands.executeCommand('setContext', key, val);
  }
}
// 唯一实例
export const global = new Global();
